// components/UploadFile.tsx
import { PlusOutlined } from '@ant-design/icons';
import type { GetProp, UploadProps } from 'antd';
import { Image, Modal, Upload, type UploadFile } from 'antd';
import { useEffect, useState } from 'react';

type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];

export type UploadFileType = 'image' | 'document' | 'all';

export interface UploadFileProps {
  value?: string | string[]; // 当前值：单个或多个文件 URL/Base64
  onChange?: (value: string | string[] | null) => void;
  listType?: 'text' | 'picture' | 'picture-card';
  fileType?: UploadFileType; // 限制文件类型
  useBase64?: boolean; // 是否使用 Base64 而非上传服务
  uploadAction?: string; // 上传接口地址（useBase64=false 时需要）
  maxCount?: number;
  showPreview?: boolean;
  beforeUpload?: (file: FileType) => boolean | Promise<void>;
  disabled?: boolean;
  accept?: string; // 自定义 accept，优先级最高
  className?: string;
  style?: React.CSSProperties;
}

const getBase64 = (file: FileType): Promise<string> =>
  new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = (error) => reject(error);
  });

// 安全提取文件名，避免 decodeURIComponent 报错
const getFileName = (url: string): string => {
  try {
    return decodeURIComponent(url.slice(url.lastIndexOf('/') + 1));
  } catch {
    return url.slice(url.lastIndexOf('/') + 1);
  }
};

const FileUploader: React.FC<UploadFileProps> = ({
  value,
  onChange,
  listType = 'picture-card',
  fileType = 'all',
  useBase64 = true,
  uploadAction,
  maxCount = 1,
  showPreview = true,
  beforeUpload,
  disabled,
  accept: propAccept,
  className,
  style,
}) => {
  const [fileList, setFileList] = useState<UploadFile[]>([]);
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewImage, setPreviewImage] = useState('');
  const [previewName, setPreviewName] = useState('');

  // 根据 fileType 推断 accept
  const getAccept = () => {
    if (propAccept) return propAccept;
    switch (fileType) {
      case 'image':
        return 'image/*';
      case 'document':
        return '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip,.rar';
      default:
        return '*/*';
    }
  };

  const accept = getAccept();

  // 同步 value 到 fileList（支持字符串数组或单个字符串）
  const syncValueToFileList = (): UploadFile[] => {
    if (!value || (typeof value === 'string' && !value.trim())) return [];
    const urls = Array.isArray(value) ? value : [value];
    return urls.map(
      (url, index): UploadFile => ({
        uid: `-${index}`,
        name: getFileName(url),
        status: 'done',
        url,
        thumbUrl: url, // 可优化为缩略图，此处简化
      }),
    );
  };

  // 初始化 fileList
  useEffect(() => {
    if (value !== undefined) {
      setFileList(syncValueToFileList());
    }
  }, [value]);

  // 处理上传前
  const handleBeforeUpload = (file: FileType) => {
    const isValid = beforeUpload ? beforeUpload(file) : true;
    if (isValid === false) return false;
    if (useBase64) {
      return false; // 阻止自动上传，走 base64
    }
    return true; // 否则走服务上传
  };

  // 处理文件变化
  const handleChange: UploadProps['onChange'] = async ({
    fileList: newFileList,
  }) => {
    setFileList(newFileList);

    // 处理文件转换逻辑
    const processFile = async (file: UploadFile): Promise<string> => {
      if (file.response?.url) return file.response.url;
      if (file.url) return file.url;
      if (file.preview) return file.preview;
      if (useBase64 && file.originFileObj) {
        return getBase64(file.originFileObj as FileType);
      }
      return '';
    };

    // 修复：Base64模式下使用不同的筛选条件
    const validFiles = useBase64
      ? newFileList.filter(
          (file) => file.originFileObj || file.url || file.preview,
        )
      : newFileList.filter((file) => file.status === 'done');

    if (validFiles.length === 0) {
      onChange?.(maxCount === 1 ? null : []);
      return;
    }

    const processedValues = await Promise.all(validFiles.map(processFile));
    onChange?.(maxCount === 1 ? processedValues[0] : processedValues);
  };

  // 处理预览
  const handlePreview = async (file: UploadFile) => {
    if (!showPreview) return;

    let url = file.url || file.preview;

    if (!url && file.originFileObj) {
      url = await getBase64(file.originFileObj as FileType);
    }

    // 👇 关键：即使不是图片，也不要 window.open，避免跳转
    if (url?.startsWith('data:image/')) {
      setPreviewImage(url);
      setPreviewName(file.name || '预览');
      setPreviewOpen(true);
    } else if (url?.startsWith('http')) {
      // 可选：只对图片弹窗，文档才新开
      if (/\.(jpe?g|png|gif|webp|svg)$/i.test(file.name || '')) {
        setPreviewImage(url);
        setPreviewName(file.name || '预览');
        setPreviewOpen(true);
      } else {
        window.open(url, '_blank');
      }
    } else {
      // ❗兜底：不跳转！
      console.warn('无法预览的文件', file);
      return;
    }
  };

  // 上传按钮
  const uploadButton = (
    <div>
      <PlusOutlined />
      <div style={{ marginTop: 8 }}>上传</div>
    </div>
  );

  return (
    <>
      <Upload
        listType={listType}
        fileList={fileList}
        onPreview={showPreview ? handlePreview : undefined}
        onChange={handleChange}
        beforeUpload={handleBeforeUpload}
        maxCount={maxCount}
        action={useBase64 ? undefined : uploadAction}
        accept={accept}
        disabled={disabled}
        className={className}
        style={style}
        customRequest={useBase64 ? () => {} : undefined} // 阻止 Base64 模式下的上传行为
      >
        {fileList.length < maxCount ? uploadButton : null}
      </Upload>

      {/* 图片预览 Modal */}
      <Modal
        open={previewOpen}
        footer={null}
        onCancel={() => {
          setPreviewOpen(false);
          setPreviewImage('');
          setPreviewName('');
        }}
        destroyOnHidden
      >
        <p style={{ textAlign: 'center', marginBottom: 8 }}>{previewName}</p>
        <Image src={previewImage} alt="预览" style={{ width: '100%' }} />
      </Modal>
    </>
  );
};

export default FileUploader;
